home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 15 / CU Amiga Magazine's Super CD-ROM 15 (1997)(EMAP Images)(GB)[!][issue 1997-10].iso / CUCD / Graphics / Ghostscript / source / libpng / pngread.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-12  |  24.6 KB  |  751 lines

  1.  
  2. /* pngread.c - read a PNG file
  3.  
  4.    libpng 1.0 beta 6 - version 0.96
  5.    For conditions of distribution and use, see copyright notice in png.h
  6.    Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  7.    Copyright (c) 1996, 1997 Andreas Dilger
  8.    May 12, 1997
  9.    */
  10.  
  11. #define PNG_INTERNAL
  12. #include "png.h"
  13.  
  14. /* Create a PNG structure for reading, and allocate any memory needed. */
  15. png_structp
  16. png_create_read_struct(png_charp user_png_ver, png_voidp error_ptr,
  17.    png_error_ptr error_fn, png_error_ptr warn_fn)
  18. {
  19.    png_structp png_ptr;
  20. #ifdef USE_FAR_KEYWORD
  21.    jmp_buf jmpbuf;
  22. #endif
  23.    png_debug(1, "in png_create_read_struct\n");
  24.    if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
  25.    {
  26.       return (png_structp)NULL;
  27.    }
  28. #ifdef USE_FAR_KEYWORD
  29.    if (setjmp(jmpbuf))
  30. #else
  31.    if (setjmp(png_ptr->jmpbuf))
  32. #endif
  33.    {
  34.       png_free(png_ptr, png_ptr->zbuf);
  35.       png_destroy_struct(png_ptr);
  36.       return (png_structp)NULL;
  37.    }
  38. #ifdef USE_FAR_KEYWORD
  39.    png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
  40. #endif
  41.    png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
  42.  
  43.    /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
  44.     * we must recompile any applications that use any older library version.
  45.     * For versions after libpng 1.0, we will be compatible, so we need
  46.     * only check the first digit.
  47.     */
  48.    if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
  49.        (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
  50.    {
  51.       png_error(png_ptr,
  52.          "Incompatible libpng version in application and library");
  53.    }
  54.  
  55.    /* initialize zbuf - compression buffer */
  56.    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
  57.    png_ptr->zbuf = png_malloc(png_ptr, png_ptr->zbuf_size);
  58.    png_ptr->zstream.zalloc = png_zalloc;
  59.    png_ptr->zstream.zfree = png_zfree;
  60.    png_ptr->zstream.opaque = (voidpf)png_ptr;
  61.  
  62.    switch (inflateInit(&png_ptr->zstream))
  63.    {
  64.      case Z_OK: /* Do nothing */ break;
  65.      case Z_MEM_ERROR:
  66.      case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break;
  67.      case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break;
  68.      default: png_error(png_ptr, "Unknown zlib error");
  69.    }
  70.  
  71.    png_ptr->zstream.next_out = png_ptr->zbuf;
  72.    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
  73.  
  74.    png_set_read_fn(png_ptr, NULL, NULL);
  75.  
  76.    return (png_ptr);
  77. }
  78.  
  79.  
  80. /* Initialize PNG structure for reading, and allocate any memory needed.
  81.    This interface is depreciated in favour of the png_create_read_struct(),
  82.    and it will eventually disappear. */
  83. void
  84. png_read_init(png_structp png_ptr)
  85. {
  86.    jmp_buf tmp_jmp;  /* to save current jump buffer */
  87.  
  88.    png_debug(1, "in png_read_init\n");
  89.    /* save jump buffer and error functions */
  90.    png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
  91.  
  92.    /* reset all variables to 0 */
  93.    png_memset(png_ptr, 0, sizeof (png_struct));
  94.  
  95.    /* restore jump buffer */
  96.    png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
  97.  
  98.    /* initialize zbuf - compression buffer */
  99.    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
  100.    png_ptr->zbuf = png_malloc(png_ptr, png_ptr->zbuf_size);
  101.    png_ptr->zstream.zalloc = png_zalloc;
  102.    png_ptr->zstream.zfree = png_zfree;
  103.    png_ptr->zstream.opaque = (voidpf)png_ptr;
  104.  
  105.    switch (inflateInit(&png_ptr->zstream))
  106.    {
  107.      case Z_OK: /* Do nothing */ break;
  108.      case Z_MEM_ERROR:
  109.      case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory"); break;
  110.      case Z_VERSION_ERROR: png_error(png_ptr, "zlib version"); break;
  111.      default: png_error(png_ptr, "Unknown zlib error");
  112.    }
  113.  
  114.    png_ptr->zstream.next_out = png_ptr->zbuf;
  115.    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
  116.  
  117.    png_set_read_fn(png_ptr, NULL, NULL);
  118. }
  119.  
  120. /* Read the information before the actual image data.  This has been
  121.  * changed in v0.90 to allow reading a file which already has the magic
  122.  * bytes read from the stream.  You can tell libpng how many bytes have
  123.  * been read from the beginning of the stream (up to the maxumum of 8)
  124.  * via png_set_sig_bytes(), and we will only check the remaining bytes
  125.  * here.  The application can then have access to the signature bytes we
  126.  * read if it is determined that this isn't a valid PNG file.
  127.  */
  128. void
  129. png_read_info(png_structp png_ptr, png_infop info_ptr)
  130. {
  131.    png_debug(1, "in png_read_info\n");
  132.    /* save jump buffer and error functions */
  133.    /* If we haven't checked all of the PNG signature bytes, do so now. */
  134.    if (png_ptr->sig_bytes < 8)
  135.    {
  136.       png_size_t num_checked = png_ptr->sig_bytes,
  137.                  num_to_check = 8 - num_checked;
  138.  
  139.       png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check);
  140.       png_ptr->sig_bytes = 8;
  141.  
  142.       if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
  143.       {
  144.          if (num_checked < 4 &&
  145.              png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
  146.             png_error(png_ptr, "Not a PNG file");
  147.          else
  148.             png_error(png_ptr, "PNG file corrupted by ASCII conversion");
  149.       }
  150.    }
  151.  
  152.    while (1)
  153.    {
  154.       png_byte chunk_length[4];
  155.       png_uint_32 length;
  156.  
  157.       png_read_data(png_ptr, chunk_length, 4);
  158.       length = png_get_uint_32(chunk_length);
  159.  
  160.       png_reset_crc(png_ptr);
  161.       png_crc_read(png_ptr, png_ptr->chunk_name, 4);
  162.  
  163.       png_debug1(0, "Reading %s chunk.\n", png_ptr->chunk_name);
  164.  
  165.       /* This should be a binary subdivision search or a hash for
  166.        * matching the chunk name rather than a linear search.
  167.        */
  168.       if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
  169.          png_handle_IHDR(png_ptr, info_ptr, length);
  170.       else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
  171.          png_handle_PLTE(png_ptr, info_ptr, length);
  172.       else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
  173.          png_handle_IEND(png_ptr, info_ptr, length);
  174.       else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
  175.       {
  176.          if (!(png_ptr->mode & PNG_HAVE_IHDR))
  177.             png_error(png_ptr, "Missing IHDR before IDAT");
  178.          else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
  179.                   !(png_ptr->mode & PNG_HAVE_PLTE))
  180.             png_error(png_ptr, "Missing PLTE before IDAT");
  181.  
  182.          png_ptr->idat_size = length;
  183.          png_ptr->mode |= PNG_HAVE_IDAT;
  184.          break;
  185.       }
  186. #if defined(PNG_READ_bKGD_SUPPORTED)
  187.       else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
  188.          png_handle_bKGD(png_ptr, info_ptr, length);
  189. #endif
  190. #if defined(PNG_READ_cHRM_SUPPORTED)
  191.       else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
  192.          png_handle_cHRM(png_ptr, info_ptr, length);
  193. #endif
  194. #if defined(PNG_READ_gAMA_SUPPORTED)
  195.       else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
  196.          png_handle_gAMA(png_ptr, info_ptr, length);
  197. #endif
  198. #if defined(PNG_READ_hIST_SUPPORTED)
  199.       else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
  200.          png_handle_hIST(png_ptr, info_ptr, length);
  201. #endif
  202. #if defined(PNG_READ_oFFs_SUPPORTED)
  203.       else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
  204.          png_handle_oFFs(png_ptr, info_ptr, length);
  205. #endif
  206. #if defined(PNG_READ_pCAL_SUPPORTED)
  207.       else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
  208.          png_handle_pCAL(png_ptr, info_ptr, length);
  209. #endif
  210. #if defined(PNG_READ_pHYs_SUPPORTED)
  211.       else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
  212.          png_handle_pHYs(png_ptr, info_ptr, length);
  213. #endif
  214. #if defined(PNG_READ_sBIT_SUPPORTED)
  215.       else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
  216.          png_handle_sBIT(png_ptr, info_ptr, length);
  217. #endif
  218. #if defined(PNG_READ_tEXt_SUPPORTED)
  219.       else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
  220.          png_handle_tEXt(png_ptr, info_ptr, length);
  221. #endif
  222. #if defined(PNG_READ_tIME_SUPPORTED)
  223.       else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
  224.          png_handle_tIME(png_ptr, info_ptr, length);
  225. #endif
  226. #if defined(PNG_READ_tRNS_SUPPORTED)
  227.       else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
  228.          png_handle_tRNS(png_ptr, info_ptr, length);
  229. #endif
  230. #if defined(PNG_READ_zTXt_SUPPORTED)
  231.       else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
  232.          png_handle_zTXt(png_ptr, info_ptr, length);
  233. #endif
  234.       else
  235.          png_handle_unknown(png_ptr, info_ptr, length);
  236.    }
  237. }
  238.  
  239. /* optional call to update the users info_ptr structure */
  240. void
  241. png_read_update_info(png_structp png_ptr, png_infop info_ptr)
  242. {
  243.    png_debug(1, "in png_read_update_info\n");
  244.    /* save jump buffer and error functions */
  245.    if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
  246.       png_read_start_row(png_ptr);
  247.    png_read_transform_info(png_ptr, info_ptr);
  248. }
  249.  
  250. /* initialize palette, background, etc, after transformations
  251.    are set, but before any reading takes place.  This allows
  252.    the user to obtail a gamma corrected palette, for example.
  253.    If the user doesn't call this, we will do it ourselves. */
  254. void
  255. png_start_read_image(png_structp png_ptr)
  256. {
  257.    png_debug(1, "in png_start_read_image\n");
  258.    /* save jump buffer and error functions */
  259.    if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
  260.       png_read_start_row(png_ptr);
  261. }
  262.  
  263. void
  264. png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
  265. {
  266.    int ret;
  267.    png_debug2(1, "in png_read_row (row %d, pass %d)\n",
  268.       png_ptr->row_number, png_ptr->pass);
  269.    /* save jump buffer and error functions */
  270.    if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
  271.       png_read_start_row(png_ptr);
  272.  
  273. #if defined(PNG_READ_INTERLACING_SUPPORTED)
  274.    /* if interlaced and we do not need a new row, combine row and return */
  275.    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
  276.    {
  277.       switch (png_ptr->pass)
  278.       {
  279.          case 0:
  280.             if (png_ptr->row_number & 7)
  281.             {
  282.                if (dsp_row != NULL)
  283.                   png_combine_row(png_ptr, dsp_row,
  284.                      png_pass_dsp_mask[png_ptr->pass]);
  285.                png_read_finish_row(png_ptr);
  286.                return;
  287.             }
  288.             break;
  289.          case 1:
  290.             if ((png_ptr->row_number & 7) || png_ptr->width < 5)
  291.             {
  292.                if (dsp_row != NULL)
  293.                   png_combine_row(png_ptr, dsp_row,
  294.                      png_pass_dsp_mask[png_ptr->pass]);
  295.                png_read_finish_row(png_ptr);
  296.                return;
  297.             }
  298.             break;
  299.          case 2:
  300.             if ((png_ptr->row_number & 7) != 4)
  301.             {
  302.                if (dsp_row != NULL && (png_ptr->row_number & 4))
  303.                   png_combine_row(png_ptr, dsp_row,
  304.                      png_pass_dsp_mask[png_ptr->pass]);
  305.                png_read_finish_row(png_ptr);
  306.                return;
  307.             }
  308.             break;
  309.          case 3:
  310.             if ((png_ptr->row_number & 3) || png_ptr->width < 3)
  311.             {
  312.                if (dsp_row != NULL)
  313.                   png_combine_row(png_ptr, dsp_row,
  314.                      png_pass_dsp_mask[png_ptr->pass]);
  315.                png_read_finish_row(png_ptr);
  316.                return;
  317.             }
  318.             break;
  319.          case 4:
  320.             if ((png_ptr->row_number & 3) != 2)
  321.             {
  322.                if (dsp_row != NULL && (png_ptr->row_number & 2))
  323.                   png_combine_row(png_ptr, dsp_row,
  324.                      png_pass_dsp_mask[png_ptr->pass]);
  325.                png_read_finish_row(png_ptr);
  326.                return;
  327.             }
  328.             break;
  329.          case 5:
  330.             if ((png_ptr->row_number & 1) || png_ptr->width < 2)
  331.             {
  332.                if (dsp_row != NULL)
  333.                   png_combine_row(png_ptr, dsp_row,
  334.                      png_pass_dsp_mask[png_ptr->pass]);
  335.                png_read_finish_row(png_ptr);
  336.                return;
  337.             }
  338.             break;
  339.          case 6:
  340.             if (!(png_ptr->row_number & 1))
  341.             {
  342.                png_read_finish_row(png_ptr);
  343.                return;
  344.             }
  345.             break;
  346.       }
  347.    }
  348. #endif
  349.  
  350.    if (!(png_ptr->mode & PNG_HAVE_IDAT))
  351.       png_error(png_ptr, "Invalid attempt to read row data");
  352.  
  353.    png_ptr->zstream.next_out = png_ptr->row_buf;
  354.    png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
  355.    do
  356.    {
  357.       if (!(png_ptr->zstream.avail_in))
  358.       {
  359.          while (!png_ptr->idat_size)
  360.          {
  361.             png_byte chunk_length[4];
  362.  
  363.             png_crc_finish(png_ptr, 0);
  364.  
  365.             png_read_data(png_ptr, chunk_length, 4);
  366.             png_ptr->idat_size = png_get_uint_32(chunk_length);
  367.  
  368.             png_reset_crc(png_ptr);
  369.             png_crc_read(png_ptr, png_ptr->chunk_name, 4);
  370.             if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
  371.                png_error(png_ptr, "Not enough image data");
  372.          }
  373.          png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
  374.          png_ptr->zstream.next_in = png_ptr->zbuf;
  375.          if (png_ptr->zbuf_size > png_ptr->idat_size)
  376.             png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
  377.          png_crc_read(png_ptr, png_ptr->zbuf,
  378.             (png_size_t)png_ptr->zstream.avail_in);
  379.          png_ptr->idat_size -= png_ptr->zstream.avail_in;
  380.       }
  381.       ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
  382.       if (ret == Z_STREAM_END)
  383.       {
  384.          if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in ||
  385.             png_ptr->idat_size)
  386.             png_error(png_ptr, "Extra compressed data");
  387.          png_ptr->mode |= PNG_AFTER_IDAT;
  388.          png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
  389.          break;
  390.       }
  391.       if (ret != Z_OK)
  392.          png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
  393.                    "Decompression error");
  394.  
  395.    } while (png_ptr->zstream.avail_out);
  396.  
  397.    png_ptr->row_info.color_type = png_ptr->color_type;
  398.    png_ptr->row_info.width = png_ptr->iwidth;
  399.    png_ptr->row_info.channels = png_ptr->channels;
  400.    png_ptr->row_info.bit_depth = png_ptr->bit_depth;
  401.    png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
  402.    png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
  403.       (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
  404.  
  405.    png_read_filter_row(png_ptr, &(png_ptr->row_info),
  406.       png_ptr->row_buf + 1, png_ptr->prev_row + 1,
  407.       (int)(png_ptr->row_buf[0]));
  408.  
  409.    png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1);
  410.  
  411.    if (png_ptr->transformations)
  412.       png_do_read_transformations(png_ptr);
  413.  
  414. #if defined(PNG_READ_INTERLACING_SUPPORTED)
  415.    /* blow up interlaced rows to full size */
  416.    if (png_ptr->interlaced &&
  417.       (png_ptr->transformations & PNG_INTERLACE))
  418.    {
  419.       if (png_ptr->pass < 6)
  420.          png_do_read_interlace(&(png_ptr->row_info),
  421.             png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
  422.  
  423.       if (dsp_row != NULL)
  424.          png_combine_row(png_ptr, dsp_row,
  425.             png_pass_dsp_mask[png_ptr->pass]);
  426.       if (row != NULL)
  427.          png_combine_row(png_ptr, row,
  428.             png_pass_mask[png_ptr->pass]);
  429.    }
  430.    else
  431. #endif
  432.    {
  433.       if (row != NULL)
  434.          png_combine_row(png_ptr, row, 0xff);
  435.       if (dsp_row != NULL)
  436.          png_combine_row(png_ptr, dsp_row, 0xff);
  437.    }
  438.    png_read_finish_row(png_ptr);
  439. }
  440.  
  441. /* Read one or more rows of image data.  If the image is interlaced,
  442.    and png_set_interlace_handling() has been called, the rows need to
  443.    to contain the contents of the rows from the previous pass.  If
  444.    the image has alpha or transparency, and png_handle_alpha() has been
  445.    called, the rows contents must be initialized to the contents of the
  446.    screen.  "row" holds the actual image, and pixels are placed in it
  447.    as they arrive.  If the image is displayed after each pass, it will
  448.    appear to "sparkle" in.  "display_row" can be used to display a
  449.    "chunky" progressive image, with finer detail added as it becomes
  450.    available.  If you do not want this "chunky" display, you may pass
  451.    NULL for display_row.  If you do not want the sparkle display, and
  452.    you have not called png_handle_alpha(), you may pass NULL for rows.
  453.    If you have called png_handle_alpha(), and the image has either an
  454.    alpha channel or a transparency chunk, you must provide a buffer for
  455.    rows.  In this case, you do not have to provide a display_row buffer
  456.    also, but you may.  If the image is not interlaced, or if you have
  457.    not called png_set_interlace_handling(), the display_row buffer will
  458.    be ignored, so pass NULL to it. */
  459.  
  460. void
  461. png_read_rows(png_structp png_ptr, png_bytepp row,
  462.    png_bytepp display_row, png_uint_32 num_rows)
  463. {
  464.    png_uint_32 i;
  465.    png_bytepp rp;
  466.    png_bytepp dp;
  467.  
  468.    png_debug(1, "in png_read_rows\n");
  469.    /* save jump buffer and error functions */
  470.    rp = row;
  471.    dp = display_row;
  472.    for (i = 0; i < num_rows; i++)
  473.    {
  474.       png_bytep rptr;
  475.       png_bytep dptr;
  476.  
  477.       if (rp != NULL)
  478.          rptr = *rp;
  479.       else
  480.          rptr = NULL;
  481.       if (dp != NULL)
  482.          dptr = *dp;
  483.       else
  484.          dptr = NULL;
  485.       png_read_row(png_ptr, rptr, dptr);
  486.       if (row != NULL)
  487.          rp++;
  488.       if (display_row != NULL)
  489.          dp++;
  490.    }
  491. }
  492.  
  493. /* Read the entire image.  If the image has an alpha channel or a tRNS
  494.    chunk, and you have called png_handle_alpha(), you will need to
  495.    initialize the image to the current image that PNG will be overlaying.
  496.    We set the num_rows again here, in case it was incorrectly set in
  497.    png_read_start_row() by a call to png_read_update_info() or
  498.    png_start_read_image() if png_set_interlace_handling() wasn't called
  499.    prior to either of these functions like it should have been.  You can
  500.    only call this function once.  If you desire to have an image for
  501.    each pass of a interlaced image, use png_read_rows() instead */
  502. void
  503. png_read_image(png_structp png_ptr, png_bytepp image)
  504. {
  505.    png_uint_32 i;
  506.    int pass, j;
  507.    png_bytepp rp;
  508.  
  509.    png_debug(1, "in png_read_image\n");
  510.    /* save jump buffer and error functions */
  511.    pass = png_set_interlace_handling(png_ptr);
  512.  
  513.    png_ptr->num_rows = png_ptr->height; /* Make sure this is set correctly */
  514.  
  515.    for (j = 0; j < pass; j++)
  516.    {
  517.       rp = image;
  518.       for (i = 0; i < png_ptr->height; i++)
  519.       {
  520.          png_read_row(png_ptr, *rp, NULL);
  521.          rp++;
  522.       }
  523.    }
  524. }
  525.  
  526. /* Read the end of the PNG file.  Will not read past the end of the
  527.    file, will verify the end is accurate, and will read any comments
  528.    or time information at the end of the file, if info is not NULL. */
  529. void
  530. png_read_end(png_structp png_ptr, png_infop info_ptr)
  531. {
  532.    png_byte chunk_length[4];
  533.    png_uint_32 length;
  534.  
  535.    png_debug(1, "in png_read_end\n");
  536.    /* save jump buffer and error functions */
  537.    png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */
  538.  
  539.    do
  540.    {
  541.       png_read_data(png_ptr, chunk_length, 4);
  542.       length = png_get_uint_32(chunk_length);
  543.  
  544.       png_reset_crc(png_ptr);
  545.       png_crc_read(png_ptr, png_ptr->chunk_name, 4);
  546.  
  547.       png_debug1(0, "Reading %s chunk.\n", png_ptr->chunk_name);
  548.  
  549.       if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
  550.          png_handle_IHDR(png_ptr, info_ptr, length);
  551.       else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
  552.       {
  553.          /* Zero length IDATs are legal after the last IDAT has been
  554.           * read, but not after other chunks have been read.
  555.           */
  556.          if (length > 0 || png_ptr->mode & PNG_AFTER_IDAT)
  557.             png_error(png_ptr, "Too many IDAT's found");
  558.          else
  559.             png_crc_finish(png_ptr, 0);
  560.       }
  561.       else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
  562.          png_handle_PLTE(png_ptr, info_ptr, length);
  563.       else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
  564.          png_handle_IEND(png_ptr, info_ptr, length);
  565. #if defined(PNG_READ_bKGD_SUPPORTED)
  566.       else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
  567.          png_handle_bKGD(png_ptr, info_ptr, length);
  568. #endif
  569. #if defined(PNG_READ_cHRM_SUPPORTED)
  570.       else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
  571.          png_handle_cHRM(png_ptr, info_ptr, length);
  572. #endif
  573. #if defined(PNG_READ_gAMA_SUPPORTED)
  574.       else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
  575.          png_handle_gAMA(png_ptr, info_ptr, length);
  576. #endif
  577. #if defined(PNG_READ_hIST_SUPPORTED)
  578.       else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
  579.          png_handle_hIST(png_ptr, info_ptr, length);
  580. #endif
  581. #if defined(PNG_READ_oFFs_SUPPORTED)
  582.       else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
  583.          png_handle_oFFs(png_ptr, info_ptr, length);
  584. #endif
  585. #if defined(PNG_READ_pCAL_SUPPORTED)
  586.       else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
  587.          png_handle_pCAL(png_ptr, info_ptr, length);
  588. #endif
  589. #if defined(PNG_READ_pHYs_SUPPORTED)
  590.       else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
  591.          png_handle_pHYs(png_ptr, info_ptr, length);
  592. #endif
  593. #if defined(PNG_READ_sBIT_SUPPORTED)
  594.       else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
  595.          png_handle_sBIT(png_ptr, info_ptr, length);
  596. #endif
  597. #if defined(PNG_READ_tEXt_SUPPORTED)
  598.       else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
  599.          png_handle_tEXt(png_ptr, info_ptr, length);
  600. #endif
  601. #if defined(PNG_READ_tIME_SUPPORTED)
  602.       else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
  603.          png_handle_tIME(png_ptr, info_ptr, length);
  604. #endif
  605. #if defined(PNG_READ_tRNS_SUPPORTED)
  606.       else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
  607.          png_handle_tRNS(png_ptr, info_ptr, length);
  608. #endif
  609. #if defined(PNG_READ_zTXt_SUPPORTED)
  610.       else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
  611.          png_handle_zTXt(png_ptr, info_ptr, length);
  612. #endif
  613.       else
  614.          png_handle_unknown(png_ptr, info_ptr, length);
  615.    } while (!(png_ptr->mode & PNG_HAVE_IEND));
  616. }
  617.  
  618. /* free all memory used by the read */
  619. void
  620. png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
  621.    png_infopp end_info_ptr_ptr)
  622. {
  623.    png_structp png_ptr = NULL;
  624.    png_infop info_ptr = NULL, end_info_ptr = NULL;
  625.  
  626.    png_debug(1, "in png_destroy_read_struct\n");
  627.    /* save jump buffer and error functions */
  628.    if (png_ptr_ptr != NULL)
  629.       png_ptr = *png_ptr_ptr;
  630.  
  631.    if (info_ptr_ptr != NULL)
  632.       info_ptr = *info_ptr_ptr;
  633.  
  634.    if (end_info_ptr_ptr != NULL)
  635.       end_info_ptr = *end_info_ptr_ptr;
  636.  
  637.    png_read_destroy(png_ptr, info_ptr, end_info_ptr);
  638.  
  639.    if (info_ptr != NULL)
  640.    {
  641.       png_destroy_struct((png_voidp)info_ptr);
  642.       *info_ptr_ptr = (png_infop)NULL;
  643.    }
  644.  
  645.    if (end_info_ptr != NULL)
  646.    {
  647.       png_destroy_struct((png_voidp)end_info_ptr);
  648.       *end_info_ptr_ptr = (png_infop)NULL;
  649.    }
  650.  
  651.    if (png_ptr != NULL)
  652.    {
  653.       png_destroy_struct((png_voidp)png_ptr);
  654.       *png_ptr_ptr = (png_structp)NULL;
  655.    }
  656. }
  657.  
  658. /* free all memory used by the read (old method) */
  659. void
  660. png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr)
  661. {
  662.    int i;
  663.    jmp_buf tmp_jmp;
  664.    png_error_ptr error_fn;
  665.    png_error_ptr warning_fn;
  666.    png_voidp error_ptr;
  667.  
  668.    png_debug(1, "in png_read_destroy\n");
  669.    /* save jump buffer and error functions */
  670.    if (info_ptr != NULL)
  671.       png_info_destroy(png_ptr, info_ptr);
  672.  
  673.    if (end_info_ptr != NULL)
  674.       png_info_destroy(png_ptr, end_info_ptr);
  675.  
  676.    png_free(png_ptr, png_ptr->zbuf);
  677.    png_free(png_ptr, png_ptr->row_buf);
  678.    png_free(png_ptr, png_ptr->prev_row);
  679. #if defined(PNG_READ_DITHER_SUPPORTED)
  680.    png_free(png_ptr, png_ptr->palette_lookup);
  681.    png_free(png_ptr, png_ptr->dither_index);
  682. #endif
  683. #if defined(PNG_READ_GAMMA_SUPPORTED)
  684.    png_free(png_ptr, png_ptr->gamma_table);
  685. #endif
  686. #if defined(PNG_READ_BACKGROUND_SUPPORTED)
  687.    png_free(png_ptr, png_ptr->gamma_from_1);
  688.    png_free(png_ptr, png_ptr->gamma_to_1);
  689. #endif
  690.    if (png_ptr->flags & PNG_FLAG_FREE_PALETTE)
  691.       png_free(png_ptr, png_ptr->palette);
  692. #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_bKGD_SUPPORTED)
  693.    if (png_ptr->flags & PNG_FLAG_FREE_TRANS)
  694.       png_free(png_ptr, png_ptr->trans);
  695. #endif
  696. #if defined(PNG_READ_hIST_SUPPORTED)
  697.    if (png_ptr->flags & PNG_FLAG_FREE_HIST)
  698.       png_free(png_ptr, png_ptr->hist);
  699. #endif
  700. #if defined(PNG_READ_GAMMA_SUPPORTED)
  701.    if (png_ptr->gamma_16_table != NULL)
  702.    {
  703.       for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
  704.       {
  705.          png_free(png_ptr, png_ptr->gamma_16_table[i]);
  706.       }
  707.    }
  708. #endif
  709. #if defined(PNG_READ_BACKGROUND_SUPPORTED)
  710.    png_free(png_ptr, png_ptr->gamma_16_table);
  711.    if (png_ptr->gamma_16_from_1 != NULL)
  712.    {
  713.       for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
  714.       {
  715.          png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
  716.       }
  717.    }
  718.    png_free(png_ptr, png_ptr->gamma_16_from_1);
  719.    if (png_ptr->gamma_16_to_1 != NULL)
  720.    {
  721.       for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
  722.       {
  723.          png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
  724.       }
  725.    }
  726.    png_free(png_ptr, png_ptr->gamma_16_to_1);
  727. #endif
  728.  
  729.    inflateEnd(&png_ptr->zstream);
  730. #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
  731.    png_free(png_ptr, png_ptr->save_buffer);
  732. #endif
  733.  
  734.    /* Save the important info out of the png_struct, in case it is
  735.     * being used again.
  736.     */
  737.    png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
  738.  
  739.    error_fn = png_ptr->error_fn;
  740.    warning_fn = png_ptr->warning_fn;
  741.    error_ptr = png_ptr->error_ptr;
  742.  
  743.    png_memset(png_ptr, 0, sizeof (png_struct));
  744.  
  745.    png_ptr->error_fn = error_fn;
  746.    png_ptr->warning_fn = warning_fn;
  747.    png_ptr->error_ptr = error_ptr;
  748.  
  749.    png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
  750. }
  751.